package com.sz.biz.logistics.core.service.impl;

import com.sz.biz.common.constants.ErrorCodes;
import com.sz.biz.common.constants.ModuleNames;
import com.sz.biz.logistics.core.entity.PriceCombo;
import com.sz.biz.logistics.core.entity.PriceComboQuotation;
import com.sz.biz.logistics.core.entity.Product;
import com.sz.biz.common.AbstractVersionEntityService;
import com.sz.biz.logistics.core.service.PriceComboQuotationService;
import com.sz.biz.logistics.core.service.PriceComboService;
import com.sz.biz.logistics.core.dto.PriceComboDto;
import com.sz.biz.logistics.core.dto.PriceComboQuotationDto;
import com.sz.biz.logistics.core.service.ProductService;
import com.sz.common.base.constants.UserActions;
import com.sz.common.base.dao.ParamData;
import com.sz.common.base.dto.QResultDto;
import com.sz.common.base.dto.QueryParams;
import com.sz.common.base.exception.Exceptions;
import com.sz.common.base.utils.EntityUtils;
import com.sz.common.core.service.PrincipalLogUtils;
import com.sz.common.core.system.service.SysUserSupport;
import com.sz.common.core.system.service.UserModel;
import com.sz.common.core.system.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.text.ParseException;
import java.util.*;

/**
 * Function: 价格套餐service <br>
 * Author: hpeng.wang. <br>
 * Date: 2017-04-18 16:46:00.
 */
@Service
public class PriceComboServiceImpl extends AbstractVersionEntityService implements PriceComboService {
    @Autowired
    private PriceComboQuotationService comboQuotationService;
    @Autowired
    private ProductService productService;
    @Autowired
    private UserService userService;
    @Autowired
    private SysUserSupport sysUserSupport;

    @Override
    protected String getMapperNamespace() {
        return "com.sz.biz.logistics.core.PriceComboMapper";
    }

    @Override
    public Integer save(PriceComboDto dto) throws ParseException {
        int id = 0;
        if (!ObjectUtils.isEmpty(dto)) {
            //1、保存基本的信息
            PriceCombo priceCombo = new PriceCombo();
            EntityUtils.copyPropertiesIgnoreNull(dto, priceCombo);
            super.save(priceCombo);

            //2、保存明细的信息
            List<PriceComboQuotation> comboQuotationList = this.assembleComboQuotation(dto.getComboQuotationDtoList(), priceCombo.getId());


            comboQuotationService.batchSave(comboQuotationList);

            //3、保存操作日志
            Map<String, Object> dataBackup = new HashMap<>();
            dataBackup.put("ADD_PRICE_COMBO", dto);
            PrincipalLogUtils.addOperationLog(ModuleNames.BIZ, ModuleNames.BIZ_PRICE_COMBO, UserActions.ADD, "添加价格套餐", dataBackup);

            //4、返回
            id = priceCombo.getId();
        }
        return id;
    }

    @Override
    public void batchDelete(List<String> uids) {
        if (!CollectionUtils.isEmpty(uids)) {
            //备份数据
            Map<String, Object> dataBackup = new HashMap<>();
            dataBackup.put("BATCH_DELETE_PRICE_COMBO", uids);
            PrincipalLogUtils.addOperationLog(ModuleNames.BIZ, ModuleNames.BIZ_PRICE_COMBO, UserActions.DELETE, "批量删除价格套餐", dataBackup);
            //保存价格套餐
            super.deleteEntities(uids);

        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Integer update(PriceComboDto dto) {
        int id = 0;
        PriceCombo priceCombo = this.findByUid(dto.getUid());
        if (!ObjectUtils.isEmpty(priceCombo)) {
            //添加要更新数据的日志信息
            Map<String, Object> dataBackup = new HashMap<>();
            dataBackup.put("UPDATE_REGION", dto);
            PrincipalLogUtils.addOperationLog(ModuleNames.BIZ, ModuleNames.BIZ_PRICE_COMBO, UserActions.UPDATE, "修改价格套餐", dataBackup);
            EntityUtils.copyPropertiesIgnoreNull(dto, priceCombo);
            super.updateVersionEntity(priceCombo);


            //2、保存明细的信息
            List<PriceComboQuotation> comboQuotationList = this.assembleComboQuotation(dto.getComboQuotationDtoList(), priceCombo.getId());
            comboQuotationService.batchSave(comboQuotationList);
            id = priceCombo.getId();

        }
        return id;
    }

    @Override
    public PriceComboDto findDtoByUid(String uid) {
        PriceComboDto priceComboDto = null;
        if (StringUtils.hasLength(uid)) {
            List<PriceComboDto> priceComboDtoList = this.findDtoByUids(Arrays.asList(uid));
            if (!CollectionUtils.isEmpty(priceComboDtoList)) {
                priceComboDto = priceComboDtoList.get(0);
            }
        }
        return priceComboDto;
    }

    @Override
    public PriceCombo findById(Integer id) {
        PriceCombo priceCombo = null;
        if (id != null && id > 0) {
            List<PriceCombo> priceComboList = this.findByIds(Arrays.asList(id));
            if (!CollectionUtils.isEmpty(priceComboList)) {
                priceCombo = priceComboList.get(0);
            }
        }
        return priceCombo;
    }

    @Override
    public String findNameByCode(String code) {
        String name = null;
        if (StringUtils.hasLength(code)) {
            name = (String) dao.findForObject(getSqlName("findNameByCode"), code);
        }
        return name;
    }

    private List<PriceCombo> findByIds(List<Integer> ids) {
        List<PriceCombo> priceComboList = null;
        if (!CollectionUtils.isEmpty(ids)) {
            ParamData pd = new ParamData();
            pd.put("ids", ids);
            priceComboList = dao.findForList(getSqlName("findByIds"), pd, PriceCombo.class);
        }
        return priceComboList;
    }

    @Override
    public Map<String, String> findCombos() {
        List<Map> list = dao.findForList(getSqlName("findCombos"), null, Map.class);
        Map<String, String> maps = new HashMap<>();
        if (!CollectionUtils.isEmpty(list)) {
            for (Map<String, String> map : list) {
                maps.put(map.get("code"), map.get("name"));
            }
        }
        return maps;
    }

    @Override
    public QResultDto findDtoByParam(QueryParams params) {
        ParamData pd = this.convertQueryParams(params);
        List<PriceCombo> list = dao.findForList(getSqlName("findByParamListPage"), pd, PriceCombo.class);

        Map<Integer, String> priceQuotationGradeMap = new HashMap<>();
        priceQuotationGradeMap.put(1, "一级");
        priceQuotationGradeMap.put(2, "二级");
        priceQuotationGradeMap.put(3, "三级");
        priceQuotationGradeMap.put(4, "四级");
        priceQuotationGradeMap.put(5, "五级");


        List<PriceComboDto> comboDtoList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(list)) {

            List<Integer> ids = new ArrayList<>();
            List<Integer> createUserIds = new ArrayList<>();
            list.forEach(priceCombo -> {
                ids.add(priceCombo.getId());
                createUserIds.add(priceCombo.getCreateUserId());
            });

            //取产品的名字
            List<PriceComboQuotation> priceComboQuotationList = comboQuotationService.findByComboIds(ids);
            List<UserModel> userModelList = sysUserSupport.getUsersById(createUserIds);
            Map<Integer, UserModel> userMap = EntityUtils.getIntKeyMapFromBeans(userModelList, "userId");


            List<String> productUidList = EntityUtils.getStringPropListFromBeans(priceComboQuotationList, "productUid");
            List<Product> productList = productService.findActivedByUids(productUidList);
            Map<String, Product> productMap = EntityUtils.getStringKeyMapFromBeans(productList, "uid");


            Map<Integer, List<PriceComboQuotationDto>> priceComboDtoMap = new HashMap<>();
            for (PriceComboQuotation priceComboQuotation : priceComboQuotationList) {
                if (!priceComboDtoMap.containsKey(priceComboQuotation.getComboId())) {
                    priceComboDtoMap.put(priceComboQuotation.getComboId(), new ArrayList<>());
                }

                PriceComboQuotationDto dto = new PriceComboQuotationDto();
                EntityUtils.copyPropertiesIgnoreNull(priceComboQuotation, dto);
                dto.setPriceQuotationGradeName(priceQuotationGradeMap.get(dto.getPriceQuotationGrade()));
                Product product = productMap.get(priceComboQuotation.getProductUid());
                if (product != null) {
                    dto.setProductName(product.getName());
                    dto.setProductCode(product.getCode());
                }


                priceComboDtoMap.get(priceComboQuotation.getComboId()).add(dto);
            }

            for (PriceCombo priceCombo : list) {
                PriceComboDto priceComboDto = new PriceComboDto();
                EntityUtils.copyPropertiesIgnoreNull(priceCombo, priceComboDto);

                //填充CreateUserName
                UserModel userModel = userMap.get(priceComboDto.getCreateUserId());
                if (!ObjectUtils.isEmpty(userModel)) {
                    priceComboDto.setCreateUserName(userModel.getAccountName());
                    priceComboDto.setFullName(userModel.getFullName());


                }

                comboDtoList.add(priceComboDto);
            }


            comboDtoList.forEach(priceComboDto -> priceComboDto.setComboQuotationDtoList(priceComboDtoMap.get(priceComboDto.getId())));

        }


        return new QResultDto(comboDtoList, pd.getPagination());
    }

    @Override
    public List<PriceComboQuotation> findPriceQuotation(String code) {
        if (StringUtils.isEmpty(code)) {
            throw Exceptions.bizException(ErrorCodes.ERROR_COMMON, "参数异常");
        }
        return comboQuotationService.findPriceQuotation(code);
    }

    /**
     * 根据uid查询激活的价格套餐数据
     *
     * @param uid 价格套餐的uid
     * @return 结果
     */
    private PriceCombo findByUid(String uid) {
        PriceCombo priceCombo = null;
        if (!ObjectUtils.isEmpty(uid)) {
            List<PriceCombo> priceComboList = findByUidAndTime(Arrays.asList(uid), true, null);
            if (!CollectionUtils.isEmpty(priceComboList)) {
                priceCombo = priceComboList.get(0);
            }
        }
        return priceCombo;
    }

    private List<PriceComboDto> findDtoByUids(List<String> uids) {
        List<PriceComboDto> priceComboDtoList = null;
        //1、查询出套餐的信息
        List<PriceCombo> priceComboList = this.findByUids(uids);

        List<Integer> ids = new ArrayList<>();
        priceComboList.forEach(priceCombo -> ids.add(priceCombo.getId()));

        if (!CollectionUtils.isEmpty(priceComboList)) {//当查询出来的信息存在时
            //根据regionIds查询出RegionItem集合，并以regionId为key拼装成map，一查性查询出来数据是为了减少数据库交互
            Map<Integer, List<PriceComboQuotationDto>> comboQuotationMap;
            comboQuotationMap = comboQuotationService.findDtoMapByComboIds(ids);
            priceComboDtoList = new ArrayList<>();
            for (PriceCombo priceCombo : priceComboList) {
                PriceComboDto dto = new PriceComboDto();//将region信息复制到regionDto中
                EntityUtils.copyPropertiesIgnoreNull(priceCombo, dto);
                //对套餐详情做添冲
                List<PriceComboQuotationDto> comboQuotationDtoList = comboQuotationMap.get(priceCombo.getId());
                dto.setComboQuotationDtoList(comboQuotationDtoList);
                priceComboDtoList.add(dto); //放到regionDtos集合中
            }
        }
        return priceComboDtoList;
    }

    private List<PriceCombo> findByUids(List<String> uids) {
        List<PriceCombo> priceComboList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(uids)) {
            ParamData pd = new ParamData();
            pd.put("uids", uids);
            priceComboList = dao.findForList(getSqlName("findByUids"), pd, PriceCombo.class);
        }
        return priceComboList;
    }

    /**
     * 根据条件查询相应的套餐信息
     *
     * @param uids     价格套餐的uid
     * @param isActive 价格套餐激活的状态 true 激活 false 未激活 null 不需要这个条件
     * @param time     时间点
     * @return 查询的套餐信息与详细信息
     */
    private List<PriceCombo> findByUidAndTime(List<String> uids, Boolean isActive, Date time) {
        List<PriceCombo> priceComboList = null;
        if (!CollectionUtils.isEmpty(uids)) {
            ParamData pd = new ParamData();
            pd.put("uids", uids);
            pd.put("isActive", isActive);
            pd.put("time", time);
            priceComboList = dao.findForList(getSqlName("findByUIdAndTime"), pd, PriceCombo.class);

            //拼装关系详情信息
            List<Integer> ids = new ArrayList<>();
            priceComboList.forEach(priceCombo -> ids.add(priceCombo.getId()));
            Map<Integer, List<PriceComboQuotation>> comboQuotation = comboQuotationService.findMapByComboIds(ids);
            for (PriceCombo priceCombo : priceComboList) {
                priceCombo.setComboQuotationList(comboQuotation.get(priceCombo.getId()));
            }
        }
        return priceComboList;
    }

    /**
     * 组装要保存的套餐集合
     *
     * @param comboQuotationDtoList 里面包含要保存的套餐明细数据
     * @param comboId               套餐表的id
     * @return 　组装好的套餐明细数据集合
     */
    private List<PriceComboQuotation> assembleComboQuotation(List<PriceComboQuotationDto> comboQuotationDtoList, int comboId) {
        List<PriceComboQuotation> comboQuotationList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(comboQuotationDtoList)) {


            for (PriceComboQuotationDto comboQuotationDto : comboQuotationDtoList) {
                comboQuotationDto.setComboId(comboId);
                int count = Collections.frequency(comboQuotationDtoList, comboQuotationDto);
                if (count > 1) {
                    throw Exceptions.bizException(ErrorCodes.ERROR_COMMON, "要保存的价格套餐有重复！");
                }
                PriceComboQuotation comboQuotation = new PriceComboQuotation();
                EntityUtils.copyPropertiesIgnoreNull(comboQuotationDto, comboQuotation);
                comboQuotation.setId(null);//保存时关系表中id不应该有数据
                comboQuotationList.add(comboQuotation);
            }
        }
        return comboQuotationList;
    }
}
